using BepuUtilities;
using System.Runtime.CompilerServices;
#if MYCODE
using BepuUtilities.Vectors;
#else
using System.Numerics;
#endif
namespace BepuPhysics.Trees
{
    public interface IOverlapHandler
    {
        void Handle(int indexA, int indexB);
    }


    partial struct Tree
    {
        // TODO：这包含许多在更老的运行时上经过经验测试的实现。
        // 我怀疑在现代版本的ryujit上会有不同的结果。特别是,递归不太可能是最快的方法。
        // (我不能立即回忆起上次是什么让非递归版本变慢了-可能是它使用了stackalloc,而我还没有意识到这一点
        // 需要清零,或者类似的东西。)

        // 请注意,所有这些实现都使用完全通用的处理程序。它可以转储到列表,也可以直接处理结果-在此
        // 我们不知道或不关心的抽象程度。这取决于用户是否使用性能最大化的处理程序(如果他们想要的话)。我们将在广泛的阶段中使用这一点。
        unsafe void DispatchTestForLeaf<TOverlapHandler>(int leafIndex, ref Vector3 leafMin, ref Vector3 leafMax, int nodeIndex, ref TOverlapHandler results) where TOverlapHandler : IOverlapHandler
        {
            if (nodeIndex < 0)
            {
                results.Handle(leafIndex, Encode(nodeIndex));
            }
            else
            {
                TestLeafAgainstNode(leafIndex, ref leafMin, ref leafMax, nodeIndex, ref results);
            }
        }
        unsafe void TestLeafAgainstNode<TOverlapHandler>(int leafIndex, ref Vector3 leafMin, ref Vector3 leafMax, int nodeIndex, ref TOverlapHandler results)
            where TOverlapHandler : IOverlapHandler
        {
            ref var node = ref Nodes[nodeIndex];
            ref var a = ref node.A;
            ref var b = ref node.B;
            // 尽管进行了递归,Leaf Bound应该保持在L1中-它将从这里一直沿递归使用。
            // 然而,虽然我们可能在加载子A时加载子B,但不能保证它会一直存在。
            // 与将派生数据保留在堆栈上相比,在驱逐情况下重新加载它需要更多的工作。
            // TODO：这是一些非常有问题的微调。发现叶子之后的递归长度足以驱逐L1的情况并不常见。一定要测试一下。
            var bIndex = b.Index;
            var aIntersects = BoundingBox.Intersects(leafMin, leafMax, a.Min, a.Max);
            var bIntersects = BoundingBox.Intersects(leafMin, leafMax, b.Min, b.Max);
            if (aIntersects)
            {
                DispatchTestForLeaf(leafIndex, ref leafMin, ref leafMax, a.Index, ref results);
            }
            if (bIntersects)
            {
                DispatchTestForLeaf(leafIndex, ref leafMin, ref leafMax, bIndex, ref results);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        unsafe void DispatchTestForNodes<TOverlapHandler>(ref NodeChild a, ref NodeChild b, ref TOverlapHandler results) where TOverlapHandler : IOverlapHandler
        {
            if (a.Index >= 0)
            {
                if (b.Index >= 0)
                {
                    GetOverlapsBetweenDifferentNodes(ref Nodes[a.Index], ref Nodes[b.Index], ref results);
                }
                else
                {
                    // 叶B对节点A。
                    TestLeafAgainstNode(Encode(b.Index), ref b.Min, ref b.Max, a.Index, ref results);
                }
            }
            else if (b.Index >= 0)
            {
                // 叶A对节点B。
                TestLeafAgainstNode(Encode(a.Index), ref a.Min, ref a.Max, b.Index, ref results);
            }
            else
            {
                // 两片叶子。
                results.Handle(Encode(a.Index), Encode(b.Index));
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static bool Intersects(in NodeChild a, in NodeChild b)
        {
            return BoundingBox.Intersects(a.Min, a.Max, b.Min, b.Max);
        }

        unsafe void GetOverlapsBetweenDifferentNodes<TOverlapHandler>(ref Node a, ref Node b, ref TOverlapHandler results) where TOverlapHandler : IOverlapHandler
        {
            // 没有共享的子项,因此请将其全部测试。
            ref var aa = ref a.A;
            ref var ab = ref a.B;
            ref var ba = ref b.A;
            ref var bb = ref b.B;
            var aaIntersects = Intersects(aa, ba);
            var abIntersects = Intersects(aa, bb);
            var baIntersects = Intersects(ab, ba);
            var bbIntersects = Intersects(ab, bb);

            if (aaIntersects)
            {
                DispatchTestForNodes(ref aa, ref ba, ref results);
            }
            if (abIntersects)
            {
                DispatchTestForNodes(ref aa, ref bb, ref results);
            }
            if (baIntersects)
            {
                DispatchTestForNodes(ref ab, ref ba, ref results);
            }
            if (bbIntersects)
            {
                DispatchTestForNodes(ref ab, ref bb, ref results);
            }
        }

        unsafe void GetOverlapsInNode<TOverlapHandler>(ref Node node, ref TOverlapHandler results) where TOverlapHandler : IOverlapHandler
        {

            ref var a = ref node.A;
            ref var b = ref node.B;

            var ab = Intersects(a, b);

            if (a.Index >= 0)
                GetOverlapsInNode(ref Nodes[a.Index], ref results);
            if (b.Index >= 0)
                GetOverlapsInNode(ref Nodes[b.Index], ref results);

            // 测试所有不同的节点。
            if (ab)
            {
                DispatchTestForNodes(ref a, ref b, ref results);
            }

        }

        public unsafe void GetSelfOverlaps<TOverlapHandler>(ref TOverlapHandler results) where TOverlapHandler : IOverlapHandler
        {
            // 如果少于两片树叶,就不可能有任何重叠。
            // 这保证了GetOverlapsInNode考虑的每个内部节点中至少有2个子节点。
            if (LeafCount < 2)
                return;

            GetOverlapsInNode(ref Nodes[0], ref results);
        }

    }
}
